/* map_grid.tcc */

#ifndef DODO_MAP_GRID_TCC
#define DODO_MAP_GRID_TCC

namespace dodo_plot
{

template <class Proj_T>
Map_Grid<Proj_T>::Map_Grid(
	const Proj_T& map_proj,
	double lon_interval, 
	double lat_interval,
	double min_lon, double max_lon,
	double min_lat, double max_lat,
	double ref_lon, double ref_lat
	)
	: map_proj_(map_proj),
	lon_interval_(lon_interval), 
	lat_interval_(lat_interval),
	min_lon_(min_lon), max_lon_(max_lon),
	min_lat_(min_lat), max_lat_(max_lat),
	ref_lon_(ref_lon), ref_lat_(ref_lat),
	line_width_(1.0), 
	line_color_(color_name::BLACK)
{ }	

template <class Proj_T>
double Map_Grid<Proj_T>::width() const
{
	return 1.0;
}

template <class Proj_T>
double Map_Grid<Proj_T>::height() const
{
	return 1.0;
}

template <class Proj_T>
Position Map_Grid<Proj_T>::local_pos() const
{
	return Position(0.0, width(), 0.0, height());
}

template <class Proj_T>
void Map_Grid<Proj_T>::draw(const Plotter& plotter) const
{
	using namespace std;

	plotter.save();

	plotter.begin_new_path();
	plotter.set_line_width(line_width_);
	plotter.set_color(line_color_);

	double lat_span = max_lat_ - min_lat_;
	double lon_span = max_lon_ - min_lon_;
	if(lon_span <= 0.0)
		lon_span += 360.0;
	
	const int LINE_PART_NUM = 50;

	vector<double> lon_parts(LINE_PART_NUM);
	vector<double> lat_parts(LINE_PART_NUM);

	for(int i = 0; i < LINE_PART_NUM; ++i)
	{
		lat_parts[i] = lat_span / (LINE_PART_NUM - 1) * i + min_lat_;
		lon_parts[i] = in_180(lon_span / (LINE_PART_NUM - 1) * i + min_lon_); 
	}
	if(min_lon_ == max_lon_)
	{
		lon_parts[0] += in_180(lon_span / 1000000);  // a little nudging
		lon_parts[LINE_PART_NUM - 1] -= in_180(lon_span / 1000000);
	}

	list<double> lons;
	list<double> lats;
	
	double first_lat = fmod(ref_lat_ - min_lat_ + 180.0, lat_interval_) + min_lat_;
	for(double lat = first_lat; lat <= max_lat_; lat += lat_interval_)
	{
		lats.push_back(lat);
	}

	double first_lon = in_180(fmod(ref_lon_ - min_lon_ + 360.0, lon_interval_) + min_lon_);
	int lon_num_max = lon_span / lon_interval_ + 1;
	for(int i = 0; i < lon_num_max; ++i)
	{
		lons.push_back(in_180(first_lon + i * lon_interval_));
	}

	for(list<double>::iterator iter = lons.begin();
		iter != lons.end(); ++iter)
	{
		double now_lon = *iter;
		Point p = map_proj_(now_lon, lat_parts[0]);
		plotter.move_to(p.x, p.y);
		for(int i = 1; i < LINE_PART_NUM; ++i)
		{
			p = map_proj_(now_lon, lat_parts[i]);
			plotter.line_to(p.x, p.y);
		}
		plotter.stroke();
	}

	for(list<double>::iterator iter = lats.begin();
		iter != lats.end(); ++iter)
	{
		double now_lat = *iter;
		Point p = map_proj_(lon_parts[0], now_lat);
		plotter.move_to(p.x, p.y);
		for(int i = 1; i < LINE_PART_NUM; ++i)
		{
			p = map_proj_(lon_parts[i], now_lat);
			plotter.line_to(p.x, p.y);
		}
		plotter.stroke();
	}	
	plotter.restore();
}



}

#endif //DODO_MAP_GRID_TCC
